#include "myutils.h"
#include <BAUTILS.H>
#include <eikenv.h>

/*
 * class dbutil
 */

#define KDBUtilUid TUid::Uid(0x080F046D)

DBUtil* DBUtil::Static()
{
	DBUtil* instance = static_cast<DBUtil*> ( CCoeEnv::Static( KDBUtilUid ) );

	if ( !instance )
	{
		instance = new ( ELeave ) DBUtil;
		instance->ConstructL();
	}

  	return instance;
}

DBUtil::DBUtil() : CCoeStatic(KDBUtilUid, -1)
{
}

void DBUtil::ConstructL()
{
}

DBUtil::~DBUtil()
{
}

//确保dest有256个字节长度
void DBUtil::ConvertDesToStr(const TPtrC& source, char* dest)
{
	dest[source.Length()] = 0;		
	for(int i = 0; i < source.Length(); i++)
	dest[i] = source[i];	
}

int DBUtil::FindByInt(c4_View* view, char* fieldname, int keyvalue)
{
	int pos = -1;
	c4_IntProp intfield(fieldname);
	pos = view->Find(intfield[keyvalue]);

	return pos;
}

int DBUtil::FindByStr(c4_View* view, char* fieldname, char* keyvalue)
{
	int pos = -1;
	c4_StringProp strfield(fieldname);
	pos = view->Find(strfield[keyvalue]);

	return pos;
}

int DBUtil::FieldIntValue(c4_View* view, char* fieldname, int pos)
{
	int p = pos;
	int size = view->GetSize();
	if(pos >= size) p = size -1;

	c4_IntProp intfield(fieldname);
	int value = intfield((*view)[p]);
	return value;
}

TPtrC8 DBUtil::FieldStr8Value(c4_View* view, char* fieldname, int pos)
{	
	int p = pos;
	int size = view->GetSize();
	if(pos >= size) p = size -1;
	
	c4_StringProp strfield(fieldname);
	iStrTemp = c4_String(strfield((*view)[p]));
	return iStrTemp.Ptr8();
}

/*
 * 由xml解析下来的内容会以unicode方式写入数据库，所以提供本函数
 */

TPtrC DBUtil::FieldUnicodeValue(c4_View* view, char* fieldname, int pos, bool carriageconvert)
{
	int p = pos;
	int size = view->GetSize();
	if(pos >= size) p = size -1;

	c4_BytesProp binfield(fieldname);
	c4_Bytes bin;
	bin = binfield(((*view)[p]));

	const int len = bin.Size()/2;
	if(len == 0) return _L("");

/*该代码有问题，会产生乱码，比如伊拉克的"伊"，看来这个转换得重写
	if(carriageconvert)
	{	
		unsigned char* p = (unsigned char*)bin.Contents();
			
		for(int i = 0; i < len; i++)
		{
			if(p[i] == '\n')
				p[i] = '\f';
		}
	}
*/	
	
	TPtrC ptr((TUint16*)bin.Contents(), bin.Size()/2);
	return ptr;
}

TPtrC8 DBUtil::FieldUtf8Value(c4_View* view, char* fieldname, int pos)
{
	int p = pos;
	int size = view->GetSize();
	if(pos >= size) p = size -1;
	
	c4_BytesProp binfield(fieldname);
	c4_Bytes bin;
	bin = binfield(((*view)[p]));

	const int len = bin.Size();
	if(len == 0) return _L8("");
	
	TPtrC8 ptr8((TUint8*)bin.Contents(), len);
	
	return ptr8;
}

bool DBUtil::FindBookPrefix(const TPtrC& path)
{
	int found = path.Find(_L("book://"));
	return (found == 0);
}

TPtrC DBUtil::GetUriFileName(const TPtrC& path)
{
	TPtrC temp(path);
	
	int found = temp.LocateReverse('/');
	
	int len = temp.Length();

	if(found > 0)
		temp.Set(temp.Right(len-found-1));

	return temp;
}

TPtrC DBUtil::GetRealPath(const TPtrC& path)
{
	int found = path.Find(_L("book://"));

	TPtrC temp(path);
	
	if(found == 0)
		temp.Set(path.Right(path.Length()-7));
	
	found = temp.Find(_L("?"));
	if(found > 0)
		temp.Set(temp.Left(found));

	return temp;
}

TPtrC DBUtil::GetPageFunc(const TPtrC& path)
{
	TPtrC temp(path);
	
	int found = temp.Find(_L("?"));
	int len = temp.Length() - found - 1;
	
	if(found > 0)
		temp.Set(temp.Right(len));
	else
		temp.Set(KNullDesC);
	
	//
	found = temp.Find(_L("("));
	if(found > 0)
		temp.Set(temp.Left(found));

	return temp;
}

TPtrC DBUtil::GetPageDesPara(const TPtrC& path, int paraindex)
{
;
}

int DBUtil::GetPageIntPara(const TPtrC& path, int paraindex)
{
	int res = -999;
	
	TPtrC temp(path);

	int found1 = temp.Find(_L("("));
	int found2 = temp.Find(_L(")"));
	int len = found2 - found1-1;

	if(found1 > 0 && found2 > 0)
	{
		temp.Set(temp.Mid(found1 + 1, len));
		TLex lex(temp);
		lex.Val(res);
	}
	
	return res;
}

//end dbutil

MyImgFile::MyImgFile()
{
	iAllocated = false;
	TBuf8<10> buf;

}

MyImgFile::~MyImgFile()
{	
_rfile.Close();
_fs.Close();	
delete iFileData8;
iFileData8 = NULL;	

}

void MyImgFile::SaveToFile(const TDesC8& data)
{
	int pos = 0;
	_rfile.Seek(ESeekEnd, pos);
	_rfile.Write(data);
}


const TPtrC8 MyImgFile::ImgBlock(int pos, int size)
{
if(iAllocated == true)
	User::Panic(_L("img error"), 0);

	iFileData8 = HBufC8::NewL(size);

	TPtr8 ptr = iFileData8->Des();
	_rfile.Read(pos, ptr, size);

	iAllocated = true;
	
	return ptr;
}


int MyImgFile::Length()
{
	int size;
	_rfile.Size(size);

	return size;
}

void MyImgFile::Init(const TDesC& FileName)
{
User::LeaveIfError(_fs.Connect());
	TBool exist = BaflUtils::FileExists(_fs, FileName);
	
	
	if(exist)
	{
		TInt aFileMode = EFileRead|EFileWrite|EFileShareAny;
		User::LeaveIfError(_rfile.Open(_fs, FileName, aFileMode));
	}
	else
	{
		TInt aFileMode = EFileRead|EFileWrite|EFileShareAny;
		
		User::LeaveIfError(_rfile.Replace(_fs, FileName, aFileMode));
	}
}


void MyImgFile::ReleaseBlock()
{
if(iAllocated == false)
	User::Panic(_L("img error"), 1);	
delete iFileData8;
iFileData8 = NULL;
iAllocated = false;
	
}

TUint32 StrUtils::StrToInt(const TDesC& aSource, TRadix aRadix)
{
	_LIT(KHexPrefix, "0x");
	_LIT(KTrue, "true");
	_LIT(KFalse, "false");
	
	if(aSource.CompareF(KTrue)==0)
		return 1;
	else if(aSource.CompareF(KFalse)==0)
		return 0;
	else if(aSource.Left(2).CompareF(KHexPrefix)==0)
	{
		TLex lex = aSource.Mid(2);
		TUint32 ret = 0;
		lex.Val(ret, EHex);
		
		return ret;	
	}
	else if(aRadix==EHex)
	{
		TLex lex = aSource;
		TUint32 ret = 0;
		lex.Val(ret, EHex);
		
		return ret;		
	}
	else 
	{
		TLex lex = aSource;
		TInt ret = 0;
		lex.Val(ret);
		
		return ret;	
	}
}

TBool StrUtils::StrToBool(const TDesC& aSource) 
{
	_LIT(K1, "1");
	_LIT(KTrue, "true");
	
	return aSource.Length()==0 || aSource.CompareF(KTrue)==0 || aSource.CompareF(K1)==0;
}

void StrUtils::Trim(TPtrC& aDest)
{
	TInt start = 0;
	while(start<aDest.Length()) 
	{
		TChar c = aDest[start];
		if(!c.IsSpace())
			break;
		
		start++;
	}
	
	if(start>=aDest.Length()) 
	{
		aDest.Set(KNullDesC);
		return;
	}
	
	TInt end = aDest.Length()-1;
	while(end>=0) 
	{
		TChar c = aDest[end];
		if(!c.IsSpace())
			break;
		
		end--;
	}
	
	aDest.Set(aDest.Mid(start, end-start+1));
}

void StrUtils::TrimRedundant(TDes& aDest)
{
	TInt writePos = 0;
	TInt first = 1;
	TInt len = aDest.Length();
	TUint16 c;
	
	for(TInt i=0;i<len;i++) 
	{
		c = aDest[i];
		if(c==' ' || c=='\t' || c==0x0B || c==0x0C)
		{
			if(first) 
			{
				aDest[writePos++] = ' ';
				first = 0;
			}
		}
		else if(c=='\r')
		{
			//ignore
		}
		else if(c=='\n')
		{
			if(first==1)
				first++;
			else if(first==2)
			{
				aDest[writePos++] = ' ';
				first = 0;
			}
		}
		else 
		{
			first = 1;
			aDest[writePos++] = c;
		}
	}
	if(writePos==1 && aDest[0]==' ')
		aDest.Zero();
	else
		aDest.SetLength(writePos);
}

TBool StrUtils::IsEmptyText(const TDesC& aSource)
{
	TInt len = aSource.Length();
	TUint16 c;
	
	for(TInt i=0;i<len;i++) 
	{
		c = aSource[i];
		if(!(c==' ' || c=='\t' || c=='\n' || c=='\r' || c==0x0B || c==0x0C || c==0xA0))
		{
			return EFalse;
		}
	}
	
	return ETrue;
}

HBufC* StrUtils::StringReplaceL(const TDesC& aSource, const TDesC& aTarget, const TDesC& aReplacement)
{
	HBufC* ret = HBufC::NewL(aSource.Length());
	TPtr dest = ret->Des();
	TInt pos1 = 0, pos2 = 0;
	do
	{
		pos2 = aSource.Mid(pos1).Find(aTarget);
		if(pos2==KErrNotFound)
		{
			TInt wantLength = aSource.Mid(pos1).Length();
			if(dest.Length() + wantLength > dest.MaxLength()) 
			{
				TInt length = dest.Length();
				ret = ret->ReAllocL(length + wantLength + 50);
				dest.Set(ret->Des());
				dest.SetLength(length);
			}
		
			dest.Append(aSource.Mid(pos1));
			break;
		}
		
		TInt wantLength = aSource.Mid(pos1, pos2).Length() + aReplacement.Length();
		if(dest.Length() + wantLength > dest.MaxLength()) 
		{
			TInt length = dest.Length();
			ret = ret->ReAllocL(length + wantLength + 50);
			dest.Set(ret->Des());
			dest.SetLength(length);
		}
		
		dest.Append(aSource.Mid(pos1, pos2));
		dest.Append(aReplacement);
		pos1 = pos1 + pos2 + aTarget.Length();
	}while(ETrue);
	
	return ret;
}

void StrUtils::StringReplace(const TDesC& aSource, const TDesC& aTarget, const TDesC& aReplacement, TDes& aDest)
{
	aDest.Zero();
	TInt pos1 = 0, pos2 = 0;
	do
	{
		pos2 = aSource.Mid(pos1).Find(aTarget);
		if(pos2==KErrNotFound)
		{
			aDest.Append(aSource.Mid(pos1));
			break;
		}
		aDest.Append(aSource.Mid(pos1, pos2));
		aDest.Append(aReplacement);
		pos1 = pos1 + pos2 + aTarget.Length();
	}while(ETrue);
}

void StrUtils::StringReplace(TDes& aTarget, TChar aSrcChar, TChar aDestChar)
{
	TInt pos1 = 0, pos2 = 0;
	while(pos1<aTarget.Length()
		&& (pos2=aTarget.Mid(pos1).Locate(aSrcChar))!=KErrNotFound) 
	{
		pos2 += pos1;
		if(aDestChar!=0) 
		{
			aTarget[pos2] = aDestChar;
			pos1 = pos2 + 1;
		}
		else 
		{
			aTarget.Delete(pos2, 1);
			pos1 = pos2;
		}	
	}
}

TBool StrUtils::StringSplit(const TDesC& aSource, TInt& aOffset, TChar aSeperator, TPtrC& aRet)
{
	if(aOffset==KErrNotFound || aOffset >= aSource.Length()) 
		return EFalse;

	do 
	{
		TInt pos = aSource.Mid(aOffset).Locate(aSeperator);
		if(pos==KErrNotFound) 
		{
			aRet.Set(aSource.Mid(aOffset));
			aOffset = aSource.Length();
			return ETrue;
		}
		
		if(pos!=0) 
		{
			aRet.Set(aSource.Mid(aOffset, pos));
			aOffset += pos + 1;
			return ETrue;
		}
		aOffset++;
	}
	while(aOffset<aSource.Length());
	
	return EFalse;
}

//tag type:0 - start tag, 1 - end tag, 2 - empty content tag
TInt StrUtils::EnumTag(const TDesC& aSource, TInt aOffset, TDes& aTagName, TInt& aLength, TInt& aTagType)
{
	TInt sourceLen = aSource.Length();
	if(aOffset>=sourceLen)
		return KErrNotFound;
	
	TInt pos;
	aTagType = 0;
	while((pos = aSource.Mid(aOffset).Locate('<'))!=KErrNotFound)
	{
		pos += aOffset;
		aOffset = pos;
		pos++;
		
		if(pos==sourceLen) 
			return KErrNotFound;

		if(aSource[pos]=='/') 
		{
			pos++;
			aTagType = 1;
		}
		else if(aSource[pos]=='!')
		{//<!-- -->
			_LIT(KCommentStart, "--");
			_LIT(KCommentEnd, "-->");
			_LIT(KCDataStart, "[CDATA[");
			_LIT(KCDataEnd, "]]>");
			
			if(pos+2<sourceLen && aSource.Mid(pos+1, 2).Compare(KCommentStart)==0) //comment
			{
				pos = aSource.Mid(aOffset).Find(KCommentEnd);
				if(pos==KErrNotFound)
					return KErrNotFound;
				
				aLength = pos + 3;
				aTagName.Copy(aSource.Mid(aOffset+1, 3));				
				return aOffset;
			}
			else if(pos+7<sourceLen && aSource.Mid(pos+1, 7).Compare(KCDataStart)==0) //cdata
			{
				aOffset = aSource.Mid(pos).Find(KCDataEnd);
				if(aOffset==KErrNotFound)
					return KErrNotFound;
				
				aOffset += pos + 3;
				if(aOffset>=sourceLen)
					return KErrNotFound;
				
				continue;
			}
		}
		
		for(;pos<sourceLen;pos++) 
		{
			TChar c(aSource[pos]);
			if(c.IsSpace() || c == '>' || c == '/') 
				break;
		}
		if(pos==sourceLen)
			return KErrNotFound;
		
		aTagName.Copy(aSource.Mid(aOffset+1, pos-aOffset-1).Left(aTagName.MaxLength()));
		if(aTagName.Length()>0 && aTagName[0]=='/')
			aTagName.Delete(0,1);
		
		TBool inattr = EFalse;
		TInt possibleEnd = -1;
		for(;pos<sourceLen;pos++) 
		{
			TChar c(aSource[pos]);
			if(c=='"') 
				inattr = !inattr;
			
			if(c=='>') 
			{
				if(!inattr) 
				{
					possibleEnd = -1;
					break;
				}

				possibleEnd = pos;
			}
			else if(c=='<')
				break;
		}
		if(possibleEnd!=-1)
			pos = possibleEnd;
		
		if(pos==sourceLen)
			return KErrNotFound;

		aLength = pos - aOffset + 1;
		if(aSource[pos - 1] == '/')
			aTagType = 2;
		else if(aTagType!=1)
			aTagType = 0;
		return aOffset;
	}
	
	return KErrNotFound;		
}

TInt StrUtils::EnumAttribute(const TDesC& aSource, TInt aOffset, TDes& aAttrName, TInt& aAttrLength, TInt& aValueStart, TInt& aValueLength)
{
	TInt sourceLen = aSource.Length();
	TBuf<50> attrNameBuf;
	TInt attrStart = -1, attrEnd = -1;
	TBool waitValue = EFalse;
	TInt i=aOffset;
	if(i<sourceLen && aSource[i]=='<') 
	{
		for(;i<sourceLen;i++)
		{
			TChar c(aSource[i]);
			if(c.IsSpace() || c == '>' || c == '/') 
				break;	
		}
	}
	
	for(;i<sourceLen;i++) 
	{
		TChar c(aSource[i]);
		if(c == '=')
		{
			TInt valueStart = i+1;
			TInt valueEnd = -1;
			TBool started = EFalse, singleQuoted = EFalse, doubleQuoted = EFalse;
			for(TInt j=i+1;j<sourceLen;j++)
			{
				TChar c(aSource[j]);
				if(c.IsSpace()) 
				{
					if(started && !(singleQuoted || doubleQuoted)) 
					{
						attrEnd = j-1;
						valueEnd = attrEnd;
						break;
					}
				}
				else if(c == '>')
				{
					//if(!(singleQuoted || doubleQuoted)) 
					{
						attrEnd = j-1;
						valueEnd = attrEnd;
						break;
					}
				}
				else if(c == '"') 
				{
					if(started) 
					{
						if(!singleQuoted) 
						{
							attrEnd = j;
							valueEnd = j-1;
							break;
						}
					}
					else 
					{
						started = ETrue;
						doubleQuoted = ETrue;
						valueStart = j+1;
					}
				}
				else if(c == '\'')
				{
					if(started) 
					{
						if(!doubleQuoted) 
						{
							attrEnd = j;
							valueEnd = j-1;
							break;	
						}
					}
					else 
					{
						started = ETrue;
						singleQuoted = ETrue;
						valueStart = j+1;
					}
				}
				else if(!started)
				{
					started = ETrue;
					valueStart = j;
				}
			}
			
			if(attrEnd!=-1) 
			{
				aAttrName.Copy(attrNameBuf);
				aValueStart = valueStart;
				aValueLength = valueEnd - valueStart + 1;
				aAttrLength = attrEnd - attrStart + 1;
				return attrStart;
			}
			else
				break;
		}
		else if(!c.IsSpace()) 
		{
			if(waitValue || c=='/' || c=='>') 
			{
				if(attrNameBuf.Length()>0) 
				{
					aAttrName.Copy(attrNameBuf);
					aValueStart = attrStart + aAttrName.Length();
					aValueLength = 0;
					aAttrLength = i - attrStart;
					return attrStart;
				}
				
				waitValue = EFalse;
				attrNameBuf.Zero();
			}
			
			if(attrNameBuf.Length()==0) 
			{
				if(c!='/')
					attrStart = i;
				else
					continue;
			}
			
			if(attrNameBuf.Length()==attrNameBuf.MaxLength())
				attrNameBuf.Zero();
			attrNameBuf.Append(c);
		}
		else 
		{
			if(attrNameBuf.Length()>0)
				waitValue = ETrue;
		}
	}

	
	return KErrNotFound;	
}

TInt StrUtils::GetAttributeValue(const TDesC& aSource, const TDesC& aAttrName, TPtrC& aDest)
{
	TBuf<50> buf;
	TInt pos = 0;
	TInt attrLength, valueStart, valueLength;
	while(ETrue)
	{
		pos = EnumAttribute(aSource, pos, buf, attrLength, valueStart, valueLength);
		if(pos==KErrNotFound)
			break;
		
		if(buf.CompareF(aAttrName)==0) 
		{
			aDest.Set(aSource.Mid(valueStart, valueLength));
			return pos;
		}
		
		pos += attrLength;
	}
	
	return KErrNotFound;	
}

TInt StrUtils::GetAttributeValue(const TDesC& aSource, const TDesC& aAttrName, TDes& aDest)
{
	TPtrC ptr;
	TInt ret = GetAttributeValue(aSource, aAttrName, ptr);
	if(ret!=KErrNotFound)
		aDest.Copy(ptr.Left(aDest.MaxLength()));

	return ret;
}
